package no.rodland.acc.model;

import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.simple.ParameterizedRowMapper;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Map;

import no.rodland.acc.db.DbRow;
import no.rodland.acc.db.FetchService;

/**
 * Created by IntelliJ IDEA.
 *
 * @Since: Jun 23, 2010 7:50:49 PM
 * @Author: fmr
 */
public class RowMappers {

    FetchService fetchService;

    public RowMappers(FetchService fetchService) {
        this.fetchService = fetchService;
    }

    public <T extends DbRow> RowMapper<T> getRowMapper(T row) {
        return getRowMapper(row.getTableName());
    }

    @SuppressWarnings({"unchecked"})
    public <T extends DbRow> RowMapper<T> getRowMapper(String tableName) {
        if ("account_groups".equals(tableName)) {
            return (RowMapper<T>) getAccountGroupRowMapper();
        }
        else if ("bank".equals(tableName)) {
            return (RowMapper<T>) getBankRowMapper(fetchService.getBankTypes(), fetchService.getBankAccounts());
        }
        else if ("bank_accounts".equals(tableName)) {
            return (RowMapper<T>) getBankAccountRowMapper();
        }
        else if ("bank_types".equals(tableName)) {
            return (RowMapper<T>) getBankTypeRowMapper();
        }
        else if ("budget".equals(tableName)) {
            return (RowMapper<T>) getBudgetRowMapper(fetchService.getBudgetAccounts(), fetchService.getBankAccounts());
        }
        else if ("budget_account_groups".equals(tableName)) {
            return (RowMapper<T>) getBudgetAccountGroupRowMapper(fetchService.getBudgetAccounts(), fetchService.getAccountGroups());
        }
        else if ("budget_accounts".equals(tableName)) {
            return (RowMapper<T>) getBudgetAccountRowMapper(fetchService.getAccountGroups());
        }
        else if ("text_budget_accounts".equals(tableName)) {
            return (RowMapper<T>) getTextBudgetAccountRowMapper(fetchService.getBudgetAccounts());
        }
//        else if ("budget_bank".equals(tableName)) {
//            return getBudgetBankRowMapper();
//        }
        throw new UnsupportedOperationException("No extractor found for " + tableName);
    }

    public RowMapper<AccountGroup> getAccountGroupRowMapper() {
        return new ParameterizedRowMapper<AccountGroup>() {
            @Override
            public AccountGroup mapRow(ResultSet rs, int rowNum) throws SQLException {
                return new AccountGroup(rs);
            }
        };
    }

    public RowMapper<Bank> getBankRowMapper(final Map<Integer, BankType> bankTypes,
                                                                final Map<Integer, BankAccount> bankAccounts) {
        return new ParameterizedRowMapper<Bank>() {
            @Override
            public Bank mapRow(ResultSet rs, int rowNum) throws SQLException {
                return new Bank(rs, bankTypes, bankAccounts);
            }
        };
    }

    public RowMapper<BankAccount> getBankAccountRowMapper() {
        return new ParameterizedRowMapper<BankAccount>() {
            @Override
            public BankAccount mapRow(ResultSet rs, int rowNum) throws SQLException {
                return new BankAccount(rs);
            }
        };
    }

    public RowMapper<BankType> getBankTypeRowMapper() {
        return new ParameterizedRowMapper<BankType>() {
            @Override
            public BankType mapRow(ResultSet rs, int rowNum) throws SQLException {
                return new BankType(rs);
            }
        };
    }

    public RowMapper<Budget> getBudgetRowMapper(final Map<Integer, BudgetAccount> budgetAccounts,
                                                                    final Map<Integer, BankAccount> bankAccounts) {
        return new ParameterizedRowMapper<Budget>() {
            @Override
            public Budget mapRow(ResultSet rs, int rowNum) throws SQLException {
                return new Budget(rs, budgetAccounts, bankAccounts);
            }
        };
    }

    public RowMapper<BudgetAccount> getBudgetAccountRowMapper(final Map<Integer, AccountGroup> accountGroups) {
        return new ParameterizedRowMapper<BudgetAccount>() {
            @Override
            public BudgetAccount mapRow(ResultSet rs, int rowNum) throws SQLException {
                return new BudgetAccount(rs, accountGroups);
            }
        };
    }

    public RowMapper<BudgetAccountGroup> getBudgetAccountGroupRowMapper(final Map<Integer, BudgetAccount> budgetAccounts,
                                                                                            final Map<Integer, AccountGroup> accountGroups) {
        return new ParameterizedRowMapper<BudgetAccountGroup>() {
            @Override
            public BudgetAccountGroup mapRow(ResultSet rs, int rowNum) throws SQLException {
                return new BudgetAccountGroup(rs, budgetAccounts, accountGroups);
            }
        };
    }

    public RowMapper<TextBudgetAccount> getTextBudgetAccountRowMapper(final Map<Integer, BudgetAccount> budgetAccounts) {
        return new ParameterizedRowMapper<TextBudgetAccount>() {
            @Override
            public TextBudgetAccount mapRow(ResultSet rs, int rowNum) throws SQLException {
                return new TextBudgetAccount(rs, budgetAccounts);
            }
        };
    }

}
